package com.ruoyi.blog.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.blog.mapper.BlogMapper;
import com.ruoyi.blog.mapper.BlogTagMapper;
import com.ruoyi.blog.mapper.WebTagMapper;
import com.ruoyi.blog.service.BlogService;
import com.ruoyi.common.constant.ActivitysConstant;
import com.ruoyi.common.constant.BlogConstant;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.BeanCopyUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.model.auth.AuthContextHolder;
import com.ruoyi.model.blog.Blog;
import com.ruoyi.model.blog.BlogTag;
import com.ruoyi.model.blog.dto.BlogDto;
import com.ruoyi.model.blog.vo.BlogAndCommonVo;
import com.ruoyi.model.blog.vo.UserAndBlogVO;
import com.ruoyi.model.comment.Comment;
import com.ruoyi.model.tag.WebTag;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class BlogServiceImpl extends ServiceImpl<BlogMapper, Blog> implements BlogService {
    @Autowired
    private BlogMapper webBlogMapper;

    @Autowired
    private WebTagMapper webTagMapper;

    @Autowired
    private BlogTagMapper blogTagMapper;
    /**
     * 密码服务
     */
    @Resource
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Resource
    private RedisCache redisCache;


    /**
     * 推送文章
     *
     * @param blogDto
     * @return
     */
    @Override
    @Transactional
    public boolean pushBlog(BlogDto blogDto) {
        // 1.为了防止恶意用户Xss攻击 所以这里需要合法用户再次输入自身密码账户密码进行验证
//        if (!bCryptPasswordEncoder.matches(blogDto.getPassword(), AuthContextHolder.getUserInfo().getPassword())) {
//            // 不通过 直接抛出异常
//            throw new RuntimeException("您的密码错误!");
//        }
        // 2. 在service校验参数 方便抛出异常
        checkValue(blogDto);
        Blog blog = BeanCopyUtils.copyBean(blogDto, Blog.class);
        blog.setViewCount(0);
        blog.setPushName(AuthContextHolder.getUserInfo().getNickName());
        blog.setPushId(AuthContextHolder.getUserId());
        blog.setStatus("1");// 默认待审核状态
        blog.setPushTime(new Date());// 当前时间就是发布时间
        blog.setIsDel("0");
        // 保存博客
        int eff = webBlogMapper.insert(blog);
        /*
        //保存web_tag表 自定义名字存进去
        List<WebTag> webTags = blogDto.getWebTags();
        int eff1 = 0;
        if (webTags != null && !webTags.isEmpty()) {
            for (WebTag webTag : webTags) {
                WebTag tags = new WebTag();
                tags.setName(webTag.getName());
                tags.setIsDel("0");
                if(webTagMapper.insertWebTag(tags)==0) {
                    eff=0;
                    break;
                }
            }

        }
        **/

        // 保存web_blog_v v tag表
        // 从BlogDto中获取博客标签列表
        List<WebTag> webTags = blogDto.getWebTags();
        // 遍历所有标签，为当前博客绑定这些标签
        for (WebTag webTag : webTags) {
            BlogTag blogTag = new BlogTag();
            // 设置标签ID和博客ID
            blogTag.setTagId(String.valueOf(webTag.getId()));
            blogTag.setBlogId(blog.getId());
            // 默认设置为未删除状态
            blogTag.setIsDel("0");
            // 尝试插入博客与标签的关联关系
            int i = blogTagMapper.insert(blogTag);
            // 如果插入失败，设置效果标志为0并跳出循环
            if (i == 0) {
                eff = 0;
                break;
            }
        }
        return eff != 0;
    }

    /**
     * 修改文章
     *
     * @param blogDTO 文章DTO
     * @return 结果
     */
    @Override
    public int updateBlog(BlogDto blogDTO) {
        //在service校验参数 方便抛出异常
        checkValue(blogDTO);
        Blog blog = BeanCopyUtils.copyBean(blogDTO, Blog.class);
        blog.setViewCount(0);
        blog.setStatus("1");// 默认待审核状态
        blog.setPushTime(new Date());// 跟新发布时间
        // 更新博客
        return webBlogMapper.updateWebBlog(blog);
    }

    /**
     * 批量删除文章
     *
     * @param ids 需要删除的文章主键
     * @return 结果
     */
    @Override
    public boolean deleteWebBlogByIds(String[] ids) {
        if (ids == null || ids.length == 0) {
            throw new IllegalArgumentException("博客ID不能为空");
        }
        try {
            webBlogMapper.deleteWebBlogByIds(ids);
            blogTagMapper.deleteWebBlogTagByBlogIds(ids);
        } catch (Exception e) {
            throw new RuntimeException("删除博客失败", e);
        }
        return true;
    }

    /**
     * 删除文章信息
     *
     * @param id 文章主键
     * @return 结果
     */
    @Override
    public boolean deleteWebBlogById(String id) {
        if (id == null || id.isEmpty()) {
            throw new IllegalArgumentException("博客ID不能为空");
        }
        try {
            webBlogMapper.deleteWebBlogById(id);
            blogTagMapper.deleteWebBlogTagBlogId(id);
        } catch (Exception e) {
            throw new RuntimeException("删除博客失败", e);
        }
        return true;
    }

    /**
     * 1. 查询首页最热门的8条文章
     *
     * @return Map<String, Object>
     */
    @Override
    public List<Blog> queryIndexBlogMap() {
        return this.webBlogMapper.selectList(Wrappers.<Blog>lambdaQuery()
                .eq(Blog::getStatus, "0")
                .orderByDesc(Blog::getViewCount).last("LIMIT 8"));
    }

    /**
     * 返回活动详情和对应的评论列表
     *
     * @param blogId 活动id
     * @param type   类型
     * @return ActivityAndCommon
     */

    @Override
    public BlogAndCommonVo getBlogAndCommonVo(String blogId, String type) {
        //1.根据活动id查询活动详情
        Blog blog = this.baseMapper.selectById(blogId);
        //使用封装的对象拷贝工具
        BlogAndCommonVo blogAndCommonVo = BeanCopyUtils.copyBean(blog, BlogAndCommonVo.class);
//        //2.查询评论列表
//        List<Comment> comments = commentMapper.selectList(Wrappers
//                .<Comment>lambdaQuery()
//                .eq(Comment::getActivityId, blogId)
//                .eq(Comment::getType, type));
//        //3.返回的是一个平铺的有关该活动的评论列表 需要准备成树形结构
//        Map<String, List<Comment>> collect = comments.stream().collect(Collectors.groupingBy(Comment::getToCommentId));
        //4.封装一个递归的方法
//        List<Comment> resultCommentList = buildCommentTree(collect, "0");
//        blogAndCommonVo.setCommentList(resultCommentList);
        //5.新增浏览量
        redisCache.incrementCacheMapValue(ActivitysConstant.BLOG_KEY, blogId, 1);
        return blogAndCommonVo;
    }

    /**
     * 审核文章状态
     *
     * @param blogId 文章ID
     * @param status 状态
     * @return 结果
     */
    @Override
    public boolean checkBlogStatus(String blogId, String status) {
        if (StringUtils.isNotEmpty(blogId) && StringUtils.isNotEmpty(status)) {
            Blog blog = this.baseMapper.selectById(blogId);
            blog.setId(blogId);
            blog.setStatus(status);
            return webBlogMapper.updateWebBlog(blog) != 0;
        }
        return false;
    }

    /**
     * 构建评论列表
     *
     * @param collect 根据所回复的Id分组的平铺数据
     * @param pId     父id
     * @return List<Comment>
     */
    private List<Comment> buildCommentTree(Map<String, List<Comment>> collect, String pId) {
        return collect.getOrDefault(pId, new ArrayList<>()).stream().map(comment ->
                comment.setChildren(buildCommentTree(collect, comment.getId()))
        ).collect(Collectors.toList());
    }

    /**
     * 根据推送ID查询索引博客列表。
     *
     * @param pushId 推送ID，用于查询与之相关的博客列表。
     * @return 返回一个博客列表，这些博客的状态为正常（status为"0"）且未被删除（is_del为"0"）。
     */
    public List<Blog> selectBlogByPushId(String pushId) {
        // 根据推送ID查询相关的博客列表
        List<Blog> pushIdBlogs = webBlogMapper.selectPushIdBlogList(pushId);
        // 转换为Stream流，并过滤出状态正常且未被删除的博客，最后将过滤结果收集到新的List中
        return pushIdBlogs.stream()
                .filter(blog -> blog.getStatus().equals("0"))
                .collect(Collectors.toList());
    }

    /**
     * 根据文章id查询对应文章
     *
     * @param id 文章主键
     * @return 文章
     */
    @Override
    public UserAndBlogVO selectWebBlogById(String id) {
        List<WebTag> webTags = null;
        Blog blog = webBlogMapper.selectWebBlogById(id);
        // 文章基本信息 新增浏览量 返回该文章对应标签名 返回发布者信息 头像 名字等等
        BlogTag blogTag = blogTagMapper.selectWebBlogTagById(id);
        List<BlogTag> blogTags = blogTagMapper.selectWebBlogTagList(blogTag);
        for (BlogTag tags : blogTags) {
            String tagId = tags.getTagId();
            WebTag webTag = webTagMapper.selectWebTagById(Long.parseLong(tagId));
            webTags = webTagMapper.selectWebTagList(webTag);
        }
        UserAndBlogVO userAndBlogVO = BeanCopyUtils.copyBean(blog, UserAndBlogVO.class);
        userAndBlogVO.setWebTags(webTags);
        return userAndBlogVO;
    }

    /**
     * 查询文章列表
     *
     * @param blog 文章
     * @return 文章
     */
    @Override
    public List<Blog> selectWebBlogList(Blog blog) {
        return webBlogMapper.selectWebBlogList(blog);
    }


    /**
     * 校验参数是否合法
     *
     * @param blogDto 用户发布的活动表单
     */
    public static void checkValue(BlogDto blogDto) {

        if (StringUtils.isEmpty(blogDto.getContent())) {
            throw new RuntimeException("文章不能为空!");
        }
        if (StringUtils.isEmpty(blogDto.getTitle())) {
            throw new RuntimeException("文章标题不能为空!");
        }
        if (StringUtils.isEmpty(blogDto.getIsComment())) {
            throw new RuntimeException("必须说明是否可以对标题进行评论!");
        }
//        if (blogDto.getBlogTags().size() < 6) {
//            throw new RuntimeException("标签数量小于5");
//        }

    }
}
